<template>
  <div class="page-setup">
    <div class="page-setup-header">
      <div class="setup-mode">
        <span class="icon iconfont icon-PC" @click="chageModel(1)"></span>
        <span class="icon iconfont icon-shouji" @click="chageModel(2)"></span>
      </div>
      <div class="setup-btn">
        <a-button type="primary" @click="submit">保存</a-button>
      </div>
    </div>
    <DesignerFilters v-if="visibleFilterModal" @close="closeFilterModal" />
    <DesignerLayout
      v-if="showLayout"
      :lays="layout"
      @confirm="layoutConfirm"
      @close="closeLayout"
    />

    <div class="page-setup-content">
      <div class="setup-tools">
        <div class="setup-layout">
          <span
            :class="item.icon"
            v-for="(item, i) in layouts"
            :key="i"
            @click="chageLayout(item)"
          ></span>
          <i
            class="icon iconfont icon-edit"
            @click="chageLayout()"
            title="布局设置"
          ></i>
          <i
            class="icon iconfont icon-shipinsuoxiao"
            @click="showFilterModal()"
            title="过滤器"
          ></i>
        </div>
        <div class="setup-row" v-for="(item, i) in components" :key="i">
          <div class="setup-cols">
            <div
              class="cols-item"
              style="
                display: flex;
                align-items: center;
                justify-content: center;
              "
              draggable="move"
              :attr-key="item.code"
            >
              {{ item.name }}
            </div>
          </div>
        </div>
      </div>
      <div class="page-container">
        <div
          class="main grid"
          :class="model === 1 ? 'pc' : 'phone'"
          :style="`--grid-template-columns: ${gridInfo.col}; --grid-template-rows: ${gridInfo.row}`"
        >
          <div
            v-for="(item, i) in gridInfo.grids"
            :key="i"
            :class="item.nm"
            class="section"
            :style="`--grid-column: ${item.ax}; --grid-row: ${item.ay}`"
            :i="i"
          >
            <div
              class="section-item"
              @mousedown="
                (ev) => {
                  ev.stopImmediatePropagation();
                }
              "
              v-for="(item2, ii) in getAttrsVal(i)"
              :key="ii"
              @click="changeComponent(item2)"
            >
              <i class="icon iconfont icon-delete" @click="remove(item2)"></i>
              <component
                :config="item2.attrs"
                :children="item2.children"
                :apk="item2.index"
                :is="getComponents(item2)"
                :select="select"
              >
              </component>
            </div>
          </div>
        </div>
      </div>
      <div class="page-setup-attrs">
        <div class="page-setup-attrs-header">
          <div class="page-setup-attrs-title">属性{{ currentIndex }}</div>
        </div>
        <div class="page-setup-attrs-content">
          <div
            v-for="(item, i) in allAttrs"
            :key="i"
            :class="className[item.componentKey]"
          >
            <DesignerAttrsSet
              v-show="item.index === currentIndex"
              :attrs="item.attrs"
              :key="i"
              @change="
                (val) => {
                  change(item, val);
                }
              "
              ref="attrsRef"
            />

            <a-button
              v-show="item.index === currentIndex"
              class="btn"
              @click="btnCK(item, item2.type)"
              :style="item2.style"
              type="primary"
              v-for="(item2, ii) in Attrs[item.componentKey].btns"
              :key="ii"
              ><i :class="item2.icon"></i>{{ item2.label }}</a-button
            >
          </div>
        </div>
      </div>
      <div v-for="(modal, i) in modals" :key="i">
        <TableModal
          v-if="modal.show"
          :models="modal"
          @close="
            (val) => {
              closeTableModal(modal, val);
            }
          "
          @change="
            (val) => {
              changeTableModal(modal, val);
            }
          "
        ></TableModal>
      </div>
    </div>
  </div>
</template>
<script setup>
import Drag from "@/utils/drag";
import * as Attrs from "@/utils/attrs";
import layouts from "@/utils/layout";
import { getComponentsAll } from "@/api/designer/components";
import { setOffPages, getPagesInfo } from "@/api/designer/pages";
import Tool from "@/utils/tool";
import { objectType } from "ant-design-vue/es/_util/type";
import { all } from "axios";

// 定义一个用于存储组件的响应式数组
const components = ref([]);
// 定义一个用于存储页面信息的响应式数组
const pageInfo = ref([]);
// 获取当前路由信息
const route = useRoute();
// 定义一个用于存储属性的响应式引用，初始值为null
const attrsRef = ref(null);
// 定义一个用于存储属性的响应式引用，初始值为null
const modalRef = ref(null);
// 定义一个用于存储模态框相关信息的响应式对象
const modals = ref([]);

// 定义一个用于存储类型信息的响应式引用
const type = ref("");
// 定义一个用于存储当前索引信息的响应式引用
const currentIndex = ref("");
// 定义一个用于存储属性信息的响应式数组
const attrs = ref([]);
// 定义一个用于存储所有组件配置对象信息的响应式数组
const allAttrs = ref([]);
// 定义一个用于存储attrs值对象信息的响应式数组
const attrsVal = ref([]);
// 定义一个用于存储页面组件排列信息的响应式数组
const setup = ref([]);
// 定义一个用于控制筛选模态框可见性的响应式引用
const visibleFilterModal = ref(false);

const visibleTableModal = ref(false);

// 定义一个对象，用于存储不同组件的CSS类名
const className = {
  table: "designer-table",
};

// 定义一个递归函数，用于遍历组件树并执行给定的函数
/**
 * 递归遍历组件树
 * @param {Array} comm - 组件数组
 * @param {Function} fun - 需要在每个组件上执行的函数
 */
const dep = (comm, fun) => {
  comm.forEach((a) => {
    if (a.children && a.children.length > 0) {
      fun(a);
      dep(a.children, fun);
    } else {
      fun(a);
    }
  });
};

/**
 * 显示筛选对话框
 * 该函数通过设置visibleFilterModal的值为true来实现筛选对话框的显示
 */
const showFilterModal = () => {
  visibleFilterModal.value = true;
};

/**
 * 关闭筛选对话框
 * 该函数通过设置visibleFilterModal的值为false来实现筛选对话框的关闭
 */
const closeFilterModal = () => {
  visibleFilterModal.value = false;
};

/**
 * 遍历所有属性模板
 */
// 导入所有位于 "./Template/**/*" 路径下的模块
const modules = import.meta.glob("./Template/**/*");
// 创建一个响应式对象 M 来存储模块
const M = ref({});

// 使用 Promise.all 确保所有异步操作完成
Promise.all(
  // 遍历模块对象的键
  Object.keys(modules).map(async (key) => {
    try {
      // 移除文件扩展名以获取干净的模块键
      const k = key.replace(".vue", "");
      // 异步加载模块
      const module = await modules[key]();
      // 将加载的模块添加到 M 中，并使用 markRaw 避免其被 Vue 的响应式系统追踪
      M.value[k] = markRaw(module.default);
    } catch (error) {
      // 如果加载模块时发生错误，记录错误信息
      console.error(`Failed to load module ${key}:`, error);
    }
  })
)
  .then(() => {
    // 所有模块加载完成后执行的逻辑
    console.log("All modules loaded successfully.");
  })
  .catch((error) => {
    // 如果 Promise.all 中有任何异步操作失败，捕获并记录错误
    console.error("Error loading modules:", error);
  });

const findTables = (arr) => {
  console.log(arr, "arrarr");
  if (arr && arr.length) {
    let i = 0;
    const tables = attrsVal.value.filter((a) => a.componentKey === "table");
    if (tables && tables.length) {
      i = arr.findIndex((a) => a.field === "assign");
      if (i > -1) {
        arr[i].options = tables.map((a) => {
          return {
            label: "表格" + a.index,
            value: a.index,
          };
        });
      }
    }
    return arr;
  }
};

/**
 *  获取页面信息
 */
const getInfo = async () => {
  try {
    // 根据路由中的id获取页面信息
    const { code, data } = await getPagesInfo({
      id: route.query.id,
    });

    // 检查响应代码是否符合预期
    if (code === rescf.codeVal) {
      // 如果数据为空，抛出错误
      if (!data) {
        throw new Error("Data is null or undefined");
      }

      // 更新页面信息
      pageInfo.value = data;
      // 设置页面配置
      setup.value = data.setup;
      // 获取网格信息
      gridInfo.value = data.grids.length ? data.grids : defGrid;

      // 处理布局信息
      layout.value = gridInfo.value.grids || [];

      if (data.modals) {
        modals.value = data.modals;
      }

      // 如果存在组件信息，处理组件属性
      if (data.components) {
        attrsVal.value = data.components.map((a) => {
          a.attrs = { ...a };
          return a;
        });
        await dep(attrsVal.value, (a) => {
          const Ats =
            JSON.parse(JSON.stringify(Attrs[a.componentKey].Attrs)) || [];
          const c = Ats.map((b) => {
            if (a.attrs[b.field] !== undefined) {
              b.value = a.attrs[b.field];
            }
            return b;
          });

          allAttrs.value.push({
            index: a.index,
            componentKey: a.componentKey,
            attrs: c,
          });
        });
      }
      // 在下一个Tick中更新类型值
      nextTick(() => {
        type.value = 0;
        if (allAttrs.value.length) {
          currentIndex.value = allAttrs.value[0].index;
          attrsVal.value.forEach((a) => {
            if (a.componentKey === "table") {
              updateTableAttributes(a);
            }
            if (a.componentKey === "form") {
              const oa = allAttrs.value.find((item) => item.index === a.index);
              findTables(oa.attrs);
            }
          });
          allAttrs.value = allAttrs.value.sort((a, b) => {
            return b.index - a.index;
          });
          attrsVal.value = attrsVal.value.sort((a, b) => {
            return b.index - a.index;
          });
        }
      });
    }
  } catch (error) {
    // 捕获并记录获取页面信息时的错误
    console.error("Error fetching page info:", error);
  }
};

// 调用函数获取页面信息
getInfo();

const closeModals = () => {
  modals.value = modals.value.map((a) => {
    a.show = false;
    return a;
  });
};

/**
 * 布局
 */
const layout = ref(1);
const showLayout = ref(false);
const layoutMap = ref({});
/**
 * 更改布局函数
 * 此函数用于根据给定的项（item）来更改应用中的布局
 * 它会根据项中的地图属性来决定使用哪种布局
 * 如果项为空或者没有地图属性，则会根据当前布局或者默认布局来进行设置
 *
 * @param {Object} item - 包含布局信息的项，特别是地图属性
 */
const chageLayout = (item) => {
  // 打印当前项和布局信息，以便调试
  console.log(item, layout, "0000");

  // 根据项中的地图属性或者当前布局来设置新的布局
  layout.value =
    item && item.map
      ? item.map // 如果项存在且有地图属性，则使用项的地图属性作为新布局
      : layout.value.length
      ? layout.value // 如果当前布局不为空，则保持当前布局不变
      : layouts["3"].map; // 如果没有项或者当前布局为空，则使用默认布局

  // 设置显示布局为真，以确保新的布局能够被显示
  showLayout.value = true;
};

/**
 * 布局更新事件
 */
const confirm = (val) => {
  layoutMap.value = val;
  console.log("confirm", layoutMap.value);
};

/**
 * 获取所有设计器组件
 */
const getComponentsTabs = async () => {
  const { code, data } = await getComponentsAll();
  if (code === rescf.codeVal) {
    components.value = data;
  }
};

getComponentsTabs();

/**
 * 删除组件
 */
const remove = (item) => {
  item.attrs = {};
  attrsVal.value = attrsVal.value.filter((a) => a.index !== item.index);
  allAttrs.value = allAttrs.value.filter(
    (a) => a.index.indexOf(item.index) === -1
  );
  modals.value = modals.value.filter((a) => a.index !== item.index);
  if (attrsVal.value && !attrsVal.value.length) {
    currentIndex.value = "";
    return;
  }
  if (attrsVal.value[0].children && attrsVal.value[0].children.length) {
    currentIndex.value = attrsVal.value[0].children[0].index;
  } else {
    currentIndex.value = attrsVal.value[0].index;
  }
};

/**
 * 切换设计器组件
 */
const changeComponent = (item) => {
  let key = item.index;
  if (!key) return;
  currentIndex.value = key;
  closeModals();
};

/**
 * 显示模式 1pc 2手机
 */
const model = ref(1);

/**
 * 显示模式
 */
const chageModel = (type) => {
  model.value = type;
};

/**
 * 监听属性表单变化
 */
const defGrid = {
  col: "repeat(24, minmax(0, 1fr))",
  row: "repeat(94, minmax(0, 1fr))",
  grids: [
    {
      x: 0,
      y: 0,
      w: 24,
      h: 95,
      i: 1,
      moved: false,
      ax: "1 / 25",
      ay: "1 / 95",
      nm: "gm1",
    },
  ],
};
let gridInfo = ref(defGrid);
const layoutConfirm = (val) => {
  if (val.target) return;
  gridInfo.value = { ...val };
  showLayout.value = false;
};

const closeLayout = () => {
  showLayout.value = false;
};

const extendsMap = {
  upload: {
    listType: "picture-card",
    arr2str: true,
    maxCount: 1,
    type: "Upload",
    beforeUpload: (file) => {
      const isPNG = file.type.match(/(jp(e)?g|png|gif)/g);
      const limit = file.size / 1024 / 1024 <= 10;
      if (!isPNG) {
        message.error(`请上传图片格式！`);
        return Upload.LIST_IGNORE;
      }
      if (!limit) {
        message.error(`图片大小不能大于10M！`);
        return Upload.LIST_IGNORE;
      }
      return isPNG && limit;
    },
    render: () => {
      return `<div class="upd"><i class="icon iconfont icon-tianjia1" style="font-size: 24px;"></i></div>`;
    },
  },
};

/**
 * 获取属性配置表单
 */
const getAttrs = (key, i, ap) => {
  if (!key || !Attrs[key]) return;

  const attrs = [...Attrs[key].Attrs];
  let o = {};

  attrs.forEach((item) => {
    o[item.field] = item.value;
  });

  o.componentKey = key;

  const addItem = (targetArray, componentKey, index, attrs) => {
    let arr = [...attrs];
    arr = findTables(arr);
    targetArray.push({
      componentKey,
      index,
      attrs: [...arr],
    });
  };

  const addTabelModals = (o) => {
    if (o.componentKey === "table") {
      modals.value.push({
        componentKey: o.componentKey,
        index: o.index,
        show: false,
        attrs: [
          {
            type: "Input",
            field: "title",
            allowClear: true,
          },
        ],
      });
    }
  };
  const uuid = Tool.generateShortUUID();
  if (ap) {
    const i = attrsVal.value.findIndex((a) => a.index === ap);
    if (i < 0) return;
    if (!attrsVal.value[i].children) attrsVal.value[i].children = [];
    const newIndex = `${attrsVal.value[i].index}-${uuid}`;
    console.log(key, extendsMap, '==========')
    attrsVal.value[i].children.push({
      componentKey: key,
      index: newIndex,
      attrs: { ...o, ...extendsMap[key], type: key.substr(0, 1).toUpperCase() + key.substr(1) },
    });
    addItem(allAttrs.value, key, newIndex, attrs);
    addTabelModals(o);
    currentIndex.value = newIndex;
  } else {
    const newIndex = `${i}-${uuid}`;
    o.index = newIndex;
    attrsVal.value.push(o);
    addTabelModals(o);
    addItem(allAttrs.value, key, newIndex, attrs);
    currentIndex.value = newIndex;
  }
  console.log(attrsVal.value, "attrsVal.valueattrsVal.value");
};

/**
 * 获取组件
 */
const getComponents = (item) => {
  let key = item.componentKey;

  if (key) {
    const path = key.substr(0, 1).toUpperCase() + key.substr(1);
    return M.value[`./Template/${path}`];
  }
};

/**
 * 页面装饰接口
 */
const setOff = async (config) => {
  const { code } = await setOffPages({
    id: route.query.id,
    ...config,
  });
  if (code === rescf.codeVal) {
    // router.push({ path: "/designer/project" });
    message.success("保存成功");
  }
};

/**
 * 属性验证
 */
const validate = () => {
  if (attrsRef.value) {
    const els = attrsRef.value.map((item) => {
      return item.validate();
    });
    return Promise.all(els);
  } else {
    return Promise.reject();
  }
};

/**
 * 根据给定的索引前缀过滤属性值
 *
 * 此函数的目的是从attrsVal数组中过滤出其index属性以给定前缀开头的元素
 * 这用于处理和显示与特定前缀索引相关的属性值
 *
 * @param {number} i - 索引前缀，用于过滤attrsVal数组中的元素
 * @returns {array} - 返回过滤后的数组，如果为空则返回空数组
 */
// const getAttrsVal = (i) => {
//   // 过滤attrsVal数组，找出index属性以给定前缀开头的元素
//   const arr = attrsVal.value.filter((a) => a.index.split("-")[0] * 1 === i);
//   // 检查过滤后的数组是否非空，如果是则返回，否则返回空数组
//   if (arr && arr.length) {
//     return arr;
//   } else {
//     return [];
//   }
// };

const getAttrsVal = computed(() => {
  return (i) => {
    // 过滤attrsVal数组，找出index属性以给定前缀开头的元素
    const arr = attrsVal.value.filter((a) => a.index.split("-")[0] * 1 === i);
    // 检查过滤后的数组是否非空，如果是则返回，否则返回空数组
    if (arr && arr.length) {
      return arr;
    } else {
      return [];
    }
  };
});

const dp = (arr, i) => {
  if (!Array.isArray(arr) || arr.length === 0) {
    return null; // 或者根据需求返回其他默认值
  }

  for (const item of arr) {
    if (item.index === i) {
      return item;
    }
    if (item.children && Array.isArray(item.children)) {
      const result = dp(item.children, i);
      if (result !== null) {
        return result;
      }
    }
  }

  return null; // 如果没有找到匹配项
};
/**
 * 监听属性表单变化
 */
const change = (item, val) => {
  if (val.target) return;
  let o = dp(attrsVal.value, item.index);
  if (o) {
    o.attrs = Object.assign({}, o.attrs, val);
    if (o.componentKey === "table") {
      o.attrs._esr = val;
    }
    o = Object.assign({}, o, val);
    console.log(o, "ooooooo");
  }
};

/**
 * 选择项函数
 * 该函数用于处理当一个项被选择时的逻辑
 * @param {any} item - 被选择的项
 */
const select = (index) => {
  currentIndex.value = index;
  closeModals();
};

/**
 * 提交函数
 *
 * 该函数是异步的，主要用于在验证表单有效性之后提交表单数据
 * 它首先调用验证函数来检查表单的数据是否有效如果验证通过，
 * 则调用 setOff 函数来提交表单数据
 */
const submit = async () => {
  // 调用验证函数，并等待验证结果
  const valid = await validate();

  // 如果验证结果为 true，则执行提交操作
  if (valid) {
    setOff({
      project: pageInfo.value.project,
      url: pageInfo.value.url,
      name: pageInfo.value.name,
      components: attrsVal.value.sort((a, b) => b.index - a.index),
      grids: gridInfo.value,
      modals: modals.value,
    });
  }
};

/**
 * 更新表格属性列
 * @param {Object} val - 包含表格属性的对象
 */
const updateTableAttributes = (val) => {
  // 验证输入
  if (!val || typeof val !== "object" || !("index" in val)) {
    console.error('Invalid input: val must be an object with "index" property');
    return;
  }

  const updatedAttributes = [];
  const suffixMap = {};
  const FIELD_SUFFIXES = ["title", "key", "slotName", "adb"]; // 提升为常量
  const validKeyPattern = /^[\w-]+-(\w+)$/; // 更严格的正则表达式

  // 处理 val 中的键值对
  Object.keys(val).forEach((key) => {
    const match = key.match(validKeyPattern);
    if (match) {
      const [prefix, suffix] = key.split("-");
      if (!suffixMap[suffix]) suffixMap[suffix] = {};
      suffixMap[suffix][prefix] = val[key];
    }
  });
  try {
    Object.keys(suffixMap).forEach((suffix) => {
      const valMap = suffixMap[suffix];
      let filteredAttrs = JSON.parse(JSON.stringify(Attrs["table"].Bttrs)); // 深拷贝
      const processedAttrs = filteredAttrs.map((a) => {
        FIELD_SUFFIXES.forEach((field) => {
          if (a.field.includes(field)) {
            a.field = `${field}-${suffix}`;
            a.value = valMap[field] || "";
          }
        });
        return a;
      });
      updatedAttributes.push(...processedAttrs);
    });

    const indexPosition = allAttrs.value.findIndex(
      (a) => a.index === val.index
    );
    if (indexPosition > -1) {
      try {
        attrsRef.value[indexPosition].addForm(updatedAttributes, true);
        // attrsRef.value[indexPosition].setForm(val);
      } catch (error) {
        console.error("Error updating form:", error.message);
      }
    } else {
      console.warn("No matching index found in allAttrs.value");
    }
  } catch (error) {
    console.error("Error processing table attributes:", error.message);
  }
};

const addTableCol = () => {
  const i = allAttrs.value.findIndex((a) => a.index === currentIndex.value);
  // const d = dp(attrsVal.value, currentIndex.value);
  if (i > -1) {
    let c = JSON.parse(JSON.stringify(Attrs["table"].Bttrs));
    let uuid = Tool.uuid();
    let a = c.map((a) => {
      if (a.field) {
        a.field = a.field.replace(/\-[a-zA-Z0-9-_]+$/, "") + "-" + uuid;
      }
      return a;
    });
    console.log(a, "====a====");
    attrsRef.value[i].addForm(a);
  }
};

const changeTableModal = (modal, val) => {
  if (val.target) return;
  console.log(modal, val, "changeTableModal");
  const i = modals.value.findIndex((a) => a.index === modal.index);
  if (i > -1) {
    const arr = val.slice(1);
    const attrs = arr.map((a) => {
      a.rules = a.required
        ? [
            {
              type: RuleMap[a.type],
              required: true,
              message: `${a.label}不能为空`,
              trigger: "blur",
            },
          ]
        : [];
      return a;
    });
    modals.value[i].title = val[0].label;
    modals.value[i].attrs = attrs;
  }
  console.log(val, "modals.value");
};

const closeTableModal = () => {
  const modal = modals.value.find((a) => a.index === currentIndex.value);
  console.log(modal, "modalmodal");
  if (modal) {
    modal.show = false;
  }
};

const showTableModal = () => {
  const modal = modals.value.find((a) => a.index === currentIndex.value);
  console.log(modals, currentIndex.value, "modalmodalmodalmodal");
  if (modal) {
    modal.show = true;
  }
};

const btnCK = (item, type) => {
  if (type === "add") {
    if (item.componentKey === "table") {
      addTableCol();
    }
  } else if (type === "modal") {
    showTableModal();
  }
};

const setAttrs = (val) => {
  const a = Tool.toObject(val);
  const key = Object.keys(a.d)[0];
  const s = currentIndex.value.split("-");
  const i = allAttrs.value.findIndex((a) => a.index === currentIndex.value);
  const d = dp(attrsVal.value, currentIndex.value);
  if (d) {
    d.attrs.filterObj = a.d;
  }
  if (i > -1) {
    attrsRef.value[i].setForm(
      Object.assign({}, d.attrs, { options: `Filters.list("${key}")` })
    );
  }
};

onMounted(() => {
  /**
   * 初始化拖拽功能
   * 在组件挂载时创建拖拽对象，以实现页面元素的拖拽排序功能
   */
  new Drag({
    container: ".designer-advertising", // 拖拽元素所在容器的className
    targetEl: "section", // 拖拽目标元素容器的className
    moveEl: "drag-move_style", // 拖拽元素的className
    dragEl: "designer", // 拖拽元素属性标识
    scrollEl: "#app", // 页面滚动元素的选择器
    end: (el1, el2, sort) => {
      // 拖拽结束时的回调函数
      // 重置attrs数组，用于更新数据
      attrs.value = [];
      // 获取拖拽元素的类型
      type.value = el1.getAttribute("attr-key");
      // 获取被拖拽元素的索引
      const i = el2.e.getAttribute("i");
      // 根据拖拽结果更新元素属性
      const ap = el2.e.getAttribute("data-ap");

      const setAttr = el2.e.getAttribute("data-set-attr");
      if (setAttr) {
        const node = el1.getAttribute("data-node")
          ? JSON.parse(el1.getAttribute("data-node"))
          : {};
        setAttrs(node.$$data);
      } else {
        getAttrs(type.value, i, ap);
      }
    },
  });
});
</script>
<style scoped lang="scss">
.page-setup {
  height: 100%;
  color: var(--colorTextBase);
}

.page-setup-header {
  display: flex;
  justify-content: space-between;
  border-bottom: 1px solid var(--colorBorder);
  height: 58px;
}

.setup-btn {
  width: 405px;
  display: flex;
  align-items: center;
  justify-content: flex-end;
  padding: 0 15px;
}

.setup-mode {
  display: flex;
  justify-content: center;
  margin-left: 280px;
  flex: 1;
  height: 100%;
  span {
    margin: 0 10px;
    font-size: 26px;
    padding: 15px 0;
    cursor: pointer;
  }
}

.page-setup-attrs {
  width: 435px;
  border-left: 1px solid var(--colorBorder);
  .page-setup-attrs-title {
    padding: 10px 20px;
    border-bottom: 1px solid var(--colorBorder);
    border-top: 1px solid var(--colorBorder);
    font-weight: bold;
  }
}

.page-setup-content {
  height: calc(100% - 59px);
  display: flex;
}
.setup-tools {
  width: 280px;
  height: 100%;
  border-right: 1px solid var(--colorBorder);

  border-left: 1px solid var(--colorBorder);
  h3 {
    padding: 10px 20px;
    border-bottom: 1px solid var(--colorBorder);
    border-top: 1px solid var(--colorBorder);
  }
  .setup-cols {
    padding: 0 0;
  }
  .cols-item {
    border-right: 1px solid var(--colorBorder);
    border-bottom: 1px solid var(--colorBorder);
    padding: 15px 0;
    text-align: center;
    i {
      font-size: 24px;
    }
  }
}
.flex {
  display: flex;
  flex-wrap: wrap;
}
.flex-1 {
  flex: 1;
}
.page-container {
  height: 100%;
  width: calc(100% - 280px - 435px);
  .main {
    margin: 0 auto;
    height: 100%;
    width: 100%;
    max-width: 100%;
    flex-direction: column;
    display: grid;
    grid-template-columns: var(--grid-template-columns);
    grid-template-rows: var(--grid-template-rows);

    &.pc {
      width: 100%;
    }
    &.iphone {
      width: 480px;
    }
  }

  iframe {
    width: 100%;
    height: 100%;
  }
}

.section {
  position: relative;
  width: 100%;
  grid-column: var(--grid-column);
  grid-row: var(--grid-row);
  min-width: 0px;
  display: flex;
  flex-direction: column;
  .sh {
    height: 100%;
  }
  &:hover .icon-delete {
    display: block;
  }
  &:hover .tz {
    display: block;
  }
  .section-item {
    position: relative;
    &:last-child {
      flex: 1;
    }
    &:hover {
      background-color: var(--colorBgContainer-hover);
    }
  }
  .tz {
    cursor: move;
    position: absolute;
    left: 50%;
    top: 5px;
    z-index: 10;
    font-size: 20px;
    display: none;
  }
  .icon-delete {
    font-size: 20px;
    color: #bcb8b6;
    position: absolute;
    right: 10px;
    top: 20px;
    z-index: 10;
    cursor: pointer;
    display: none;
  }
}

.setup-layout {
  display: flex;
  justify-content: center;
  align-items: center;
  height: 58px;
  border-bottom: 1px solid var(--colorBorder);
  cursor: pointer;
  background-color: var(--colorBgContainer-hover);
  .icon {
    font-size: 30px;
    margin: 0 10px;
  }
}
.btn {
  margin-left: 20px;
  .icon {
    margin-right: 10px;
  }
}

.page-setup-attrs-content {
  height: calc(100% - 60px);
  overflow: auto;
}
</style>
